using System;
using GammaJul.ReSharper.GammaXaml.Highlightings.CSharp;
using JetBrains.Annotations;
using JetBrains.DocumentModel;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Daemon;
using JetBrains.ReSharper.Daemon.Impl;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp.Tree;

[assembly: RegisterConfigurableSeverity(
	OwnerShouldBeContainingTypeHighlighting.SeverityId,
	null,
	HighlightingGroupIds.CodeSmell,
	OwnerShouldBeContainingTypeHighlighting.Description,
	OwnerShouldBeContainingTypeHighlighting.Description,
	Severity.WARNING,
	false)]

namespace GammaJul.ReSharper.GammaXaml.Highlightings.CSharp {

	/// <summary>
	/// An highlighting that represent a DependencyProperty field registration
	/// that supplies an owner that isn't the current containing type.
	/// </summary>
	[ConfigurableSeverityHighlighting(SeverityId, CSharpProjectFileType.Name, OverlapResolve = OverlapResolveKind.WARNING)]
	public class OwnerShouldBeContainingTypeHighlighting : IHighlightingWithRange {
		internal const string SeverityId = "Dp.OwnerShouldBeContainingType";
		internal const string Description = "Dependency property registration on a type other than the current containing type.";

		private readonly ITypeofExpression _typeofExpression;
		private readonly IField _dpField;
		private readonly ITypeElement _containingTypeElement;

		/// <summary>
		/// Gets the <see cref="ITypeofExpression"/> that represents a different owner.
		/// </summary>
		[NotNull]
		public ITypeofExpression TypeofExpression {
			get { return _typeofExpression; }
		}

		/// <summary>
		/// Gets the dependency property field.
		/// </summary>
		[CanBeNull]
		public IField DpField {
			get { return _dpField; }
		}

		/// <summary>
		/// Gets the containing type element.
		/// </summary>
		[NotNull]
		public ITypeElement ContainingTypeElement {
			get { return _containingTypeElement; }
		}

		public string ToolTip {
			get { return Description; }
		}

		public string ErrorStripeToolTip {
			get { return Description; }
		}

		public int NavigationOffsetPatch {
			get { return 0; }
		}

		public bool IsValid() {
			return _typeofExpression.IsValid();
		}

		public DocumentRange CalculateRange() {
			return _typeofExpression.TypeName.GetHighlightingRange();
		}

		public OwnerShouldBeContainingTypeHighlighting([NotNull] ITypeofExpression typeofExpression, [NotNull] ITypeElement containingTypeElement, [CanBeNull] IField dpField) {
			if (typeofExpression == null)
				throw new ArgumentNullException("typeofExpression");
			if (containingTypeElement == null)
				throw new ArgumentNullException("containingTypeElement");

			_typeofExpression = typeofExpression;
			_containingTypeElement = containingTypeElement;
			_dpField = dpField;
		}
	}

}
